const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// then all 方法
class myPromis {
  #state = PENDING;
  #result = undefined;
  #handler = [];

  constructor(excurtor) {
    const resolve = (data) => {
      this.#changeState(FULFILLED, data);
    };
    const reject = (reason) => {
      this.#changeState(REJECTED, reason);
    };
    try {
      excurtor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  #changeState(state, result) {
    if (this.#state !== PENDING) return;
    this.#state = state;
    this.#result = result;
    this.#run();
  }

  #isPromisLike(value) {
    return value instanceof myPromis || (value && typeof value.then === 'function');
  }

  #runOne(callBack, resolve, reject) {
    if (typeof callBack !== 'function') {
      try {
        const settled = this.#state === FULFILLED ? resolve : reject;
        settled(this.#result);
        return;
      } catch (error) {
        reject(error);
      }
    }
    try {
      const data = callBack(this.#result);
      if (this.#isPromisLike(data)) {
        data.then(resolve, reject);
      } else {
        resolve(data);
      }
    } catch (error) {
      reject(error);
    }
  }

  #run() {
    if (this.#state === PENDING) return;
    while (this.#handler.length) {
      const { onFulfilled, onRejected, resolve, reject } = this.#handler.shift();
      if (this.#state === FULFILLED) {
        this.#runOne(onFulfilled, resolve, reject);
      } else {
        this.#runOne(onRejected, resolve, reject);
      }
    }
  }

  then(onFulfilled, onRejected) {
    return new myPromis((resolve, reject) => {
      this.#handler.push({ onFulfilled, onRejected, resolve, reject });
      this.#run();
    });
  }

  static resolve(value) {
    return new myPromis((resolve) => {
      resolve(value);
    });
  }

  static reject(reason) {
    return new myPromis((resolve, reject) => {
      reject(reason);
    });
  }

  static race(promises) {
    return new myPromis((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError('参数必须是一个可迭代的数组'));
      }

      const resolvedPromises = promises.map(promise => myPromis.resolve(promise));

      Promise.race(resolvedPromises)
        .then(resolve)
        .catch(reject);
    });
  }
}

const p = new myPromis((resolve, reject) => {
  setTimeout(() => {
    resolve(123);
  }, 1000);
});

p.then(res => {
  console.log(res);
  return '给下一个promise';
}, err => {
  console.log(err, 'err 11111');
}).then(res => {
  console.log(res, 'back');
});

const p1 = new myPromis((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 100);
});

myPromis.race([p1]).then(res => {
  console.log(res, 'back');
}, err => {
  console.log(err, 'race error');
});
// all方法
Promise.myAll = function (promises) {
  if (!Array.isArray(promises)) {
    return Promise.reject(new Error('参数必须是数组'));
  }

  return new Promise((resolve, reject) => {
    const results = [];
    let fulfilledCount = 0;

    if (promises.length === 0) {
      resolve(results);
    }

    promises.forEach((promise, index) => {
      Promise.resolve(promise).then((data) => {
        results[index] = data;
        fulfilledCount++;
        if (fulfilledCount === promises.length) {
          resolve(results);
        }
      }).catch(reject);
    });
  });
}

Promise.myAll([1, 2, 3, Promise.reject('345213')]).then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err, 'error');
});

